﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RayTracing
{
    public class Cylinder : Geometry
    {
        public float x, y, z;
        P3 center;
        float radius;
        public Cylinder()
        {
            this.center = new P3(0, 0, 0);
            this.radius = .5f;
        }
        public Cylinder(P3 center, float radius)
        {
            this.center = center;
            this.radius = radius;
        }
        public Cylinder(P3 p)
        {
            this.x = p.x;
            this.y = p.y;
            this.z = p.z;
            center = new P3(x, y, z);
            this.radius = .5f;
        }
        public Cylinder(float x, float y, float z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
            center = new P3(x, y, z);
            this.radius = .5f;
        }
        public float distance(Ray rei)
        {
            float closest = Main.infinity;
            float deltX = rei.direction.x;

            float deltY = rei.direction.y;

            float deltZ = rei.direction.z;

            float A = (rei.direction.x * rei.direction.x) + rei.direction.y * rei.direction.y;
            float B = 2 * ((rei.origin.x * deltX) + (rei.origin.y * deltY));
            float C = ((rei.origin.x * rei.origin.x) + (rei.origin.y * rei.origin.y) - 1f);
            float d = (float)(((B * B) - (4 * A * C)));
            //return 0;
            if (d > 0)
            {
                float T = (float)((-B - (Math.Sqrt(d))) / (2 * A));

                if (T < 0)
                    T = (float)((-B + (Math.Sqrt(d))) / (2 * A));
                if (T >= 0)
                {


                    P3 p = rei.travel(T);
                    if (p.z > 0 && p.z < 1)
                        closest = T;

                }
            }
            if (rei.direction.z != 0)
            {
                float t = -(rei.origin.z) / rei.direction.z;
                if (t > 0)
                {
                    P3 Point = rei.travel(t);
                    if ((Point.x * Point.x) + (Point.y * Point.y) < 1)
                        closest = Math.Min(closest, t);
                }


                t = -(rei.origin.z - 1) / rei.direction.z;
                if (t > 0)
                {
                    P3 Point = rei.travel(t);
                    if ((Point.x * Point.x) + (Point.y * Point.y) < 1)
                        closest = Math.Min(closest, t);
                }
            }

            return closest;
        }
        public P2 toP2(P3 p)
        {
            if (p.z > .999999)
                return new P2((p.x + 1f)/2, (p.y + 1f)/2, 1);
            else if (p.z < .00001)
                return new P2((p.x + 1f)/2, (p.y + 1f)/2, 2);
            else
                return new P2((float)(Math.Atan2((double)p.y, (double)p.x) / (2 * Math.PI)+ .5f), p.z, 0);
        }
        public P3 normal(P3 p)
        {
            if (p.z > .99999)
                return new P3(0, 0, 1);
            else if (p.z <= .00001)
                return new P3(0, 0, -1);
            else
                return new P3(p.x, p.y, 0);
        }
        /*
         * T = (-b +- sqrt(b^2-4ac))/2a
         * P = r.travel(t)
         * x^2 + y^2 = 1
         * (X! + TdeltX, Y! + TdeltY)
         * (X! + TdeltX)^2 + (Y! + TdeltY)^2 = 1
         * (X!^2 + 2TdeltX + T^2 + Y!^2 + 2TdeltY + T^2 = 1
         * A= 2
         * B = 2(deltX + deltY)
         * C = (X!^2 + Y!^2 - 1)
         * 2T^2 + 2(deltX + deltY)T + (X!^2 + Y!^2 - 1) = 0;
         * r = (X!, Y!, Z!)
         * (deltX,deltY,deltZ)
         * Z = Z! + TdeltZ
         * */

    }
}
